﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ParkingApp.Common;

namespace ParkingApp.ParkingSlot.Simulator.Lib {
    public class ParkingSlotAvailabilitySimulator : IParkingSlotAvailability {
        List<Slot> _slotList;
        List<Slot> SlotList { 
            get {
                _slotList = CachingService.Get<List<Slot>>(CachingService.ParkingSlotListKey);
                if (_slotList == null) {
                    PopulateSlotList();
                    CachingService.AddItem(CachingService.ParkingSlotListKey, _slotList);
                }
                return _slotList;
            } 
            set {_slotList = value;}
        }

        private void PopulateSlotList() {
            _slotList = new List<Slot>();
            int currentFloor = 1; string letter = "A";
            for (int iterationId = 0; iterationId != 50; iterationId++) {
                string slotDescription = currentFloor.ToString() + letter + (iterationId + 1).ToString();
                _slotList.Add(new Slot() { Available = true, Floor = currentFloor, PreferenceRate = iterationId+1, SlotDescription = slotDescription, SlotId = iterationId + 1 });
                if (iterationId >= 10) {letter = "B"; currentFloor+=1;}
                if (iterationId >= 20) {letter = "C"; currentFloor+=1;}
                if (iterationId >= 30) {letter = "D"; currentFloor+=1;}
                if (iterationId >= 40) {letter = "E"; currentFloor+=1;}
                if (iterationId >= 50) { letter = "F"; currentFloor += 1; }
            }
        }
        public List<Slot> GetAvailableSlots() {
            return (from a in SlotList
                                 where a.Available == true
                                 select a).ToList();
        }

        public void AllocateSlot(Slot slot) {
            var result = (from a in SlotList
                         where a.SlotId == slot.SlotId
                         select a).FirstOrDefault();
            if (!result.Available) throw new ApplicationException("Slot already allocated.");
            result.Available = false;
        }

        public void FreeUpSlot(Slot slot) {
            var result = (from a in SlotList
                          where a.SlotId == slot.SlotId
                          select a).FirstOrDefault();
            if (result.Available) throw new ApplicationException("Slot already free.");
            result.Available = true;
        }

        public void MakeSlotUnavailable(Slot parkingSlot, Slot.NotAvailableReason notAvailableReason)
        {
            var slot = (from a in SlotList
                       where a.SlotId == parkingSlot.SlotId
                       select a).FirstOrDefault();
            if (slot != null) {
                slot.Available = false;
                slot.Reason = notAvailableReason;
            }
        }
    }
}
